/*
 * @FilePath: /tads/server/core/sdk/api/api.go
 * @Author: wnina0x0
 * @Date: 2025-04-14 14:36:23
 * @Description:
 *
 * 版权信息 : 2025 by wnina0x0, All Rights Reserved.
 */
package api

import (
	"errors"
	"fmt"
	"strings"
	"tads/server/core"
	"tads/server/core/sdk"
	"tads/server/core/sdk/service"
	"tads/server/global"

	vd "github.com/bytedance/go-tagexpr/v2/validator"
	"github.com/golang-jwt/jwt/v5"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"gorm.io/gorm"
)

type Api struct {
	Context       *gin.Context
	Logger        *core.Logger
	Postgres      *gorm.DB
	Errors        error
	AuthKey       *[]byte
	Jwt           *string
	Authorization string
	Code          int
}

func (e *Api) AddError(err error) {
	if e.Errors == nil {
		e.Errors = err
		// return
	} else if err != nil {
		// if strings.Contains(e.Errors.Error(), err.Error()) {
		// 	return
		// }
		e.Logger.Error(err)
		e.Errors = fmt.Errorf("%v; %w", e.Errors, err)
	}
}

func (e *Api) CheckJwt(options ...jwt.ParserOption) *Api {
	e.Authorization = e.Context.GetHeader("Authorization")
	if strings.Compare(e.Authorization, "") == 0 {
		e.Code = 401
		e.Errors = errors.New("无登陆信息，请登陆")
	}
	token, err := jwt.Parse(e.Authorization, func(token *jwt.Token) (interface{}, error) {
		return global.TADS_AUTH_KEY, nil
	}, options...)
	if err != nil {
		e.Code = 401
		e.Errors = err
		return e
	}
	// 校验 Claims 对象是否有效，基于 exp（过期时间），nbf（不早于），iat（签发时间）等进行判断（如果有这些声明的话）。
	if !token.Valid {
		e.Code = 401
		e.Errors = errors.New("invalid token")
		return e
	}
	e.Errors = nil

	return e
}

func (e *Api) MakeContext(c *gin.Context) *Api {
	e.Context = c
	e.Logger = global.TADS_LOG
	return e
}

func (e *Api) Bind(d interface{}, bindings ...binding.Binding) *Api {
	if len(bindings) == 0 {
		bindings = constructor.GetBindingForGin(d)
	}
	e.Errors = nil
	for i := range bindings {
		var err error
		if bindings[i] == nil {
			err = e.Context.ShouldBindUri(d)
		} else {
			err = e.Context.ShouldBindWith(d, bindings[i])
		}
		if err != nil && err.Error() == "EOF" {
			e.Code = 400
			e.Logger.Warn("request body is not present anymore. ")
			err = nil
			continue
		}
		if err != nil {
			e.Code = 400
			e.AddError(err)
			break
		}
	}
	if err1 := vd.Validate(d); err1 != nil {
		e.Code = 400
		e.AddError(err1)
	}
	return e
}

func (e *Api) MakePostgres() *Api {
	var err error
	if e.Logger == nil {
		e.Code = 400
		err = errors.New("at MysqlOrm logger is nil")
		e.AddError(err)
		return e
	}
	e.Postgres = sdk.Runtime.GetGorm("postgres")
	return e
}

func (e *Api) MakeService(c *service.Service) *Api {
	c.Log = e.Logger
	c.Postgres = e.Postgres
	return e
}
